package com.vogue.flowmeter.profile;

import android.app.ProgressDialog;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.content.Intent;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
import android.view.WindowManager;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
import androidx.lifecycle.LifecycleService;

import com.vogue.flowmeter.R;
import com.vogue.flowmeter.api.event.DashboardMessageEvent;
import com.vogue.flowmeter.profile.queue.WriteQueue;

import org.greenrobot.eventbus.EventBus;
import no.nordicsemi.android.ble.data.Data;
import no.nordicsemi.android.ble.livedata.state.ConnectionState;
import no.nordicsemi.android.ble.utils.ILogger;
import no.nordicsemi.android.log.ILogSession;
import no.nordicsemi.android.log.Logger;

/**
 *蓝牙管理器服务
 * 使用LifecycleService监听Service的生命周期
 * 通过蓝牙服务Binder被共享使在不同的activity里面获取到已连接的蓝牙管理器
 */
public  class BleProfileService extends LifecycleService {
    private static final String TAG = "BleProfileService";

    private BleProfileManager bleManager;
    private Handler handler;
    private ILogSession logSession;
    private ProgressDialog dialog;



    public class LocalBinder extends Binder implements ILogger {
        /**
         *重新连接到以前连接的设备
         *如果不支持此设备，则在断开连接时清除其服务，因此重新连接可能会有帮助
         */
        public void reconnect(BluetoothDevice device) {
            if (device != null) {
                bleManager.connect(device)
                        .retry(3, 100)
                        .useAutoConnect(false)
                        .enqueue();
            }
        }
        public void onConnection(BluetoothDevice device){
            Log.e(TAG,"onConnection");
            if (bleManager==null){
                showToast("蓝牙管理器异常");
                return;
            }
            reconnect(device);
            bleManager.getState().observe(BleProfileService.this, state -> {
                switch (state.getState()) {
                    case CONNECTING:
                        Log.e(TAG,"onConnection CONNECTING");
                        dialog.setTitle(R.string.state_connecting);
                        dialog.show();
                        break;
                    case INITIALIZING:
                        Log.e(TAG,"onConnection INITIALIZING");
                        dialog.setTitle(R.string.state_initializing);
                        dialog.show();
                        break;
                    case READY:
                        Log.e(TAG,"onConnection READY");
                        dialog.dismiss();
                        showToast("设备已准备就绪");
                        device.createBond();
                        //发送事件出去
                        DashboardMessageEvent event = new DashboardMessageEvent("Dashboard","设备已准备就绪");
                        EventBus.getDefault().post(event);
                        break;
                    case DISCONNECTED:
                        Log.e(TAG,"onConnection DISCONNECTED");
                        dialog.dismiss();
                        if (state instanceof ConnectionState.Disconnected) {
                            final ConnectionState.Disconnected stateWithReason = (ConnectionState.Disconnected) state;
                            if (stateWithReason.isNotSupported()) {
                                showToast("设备不支持");
                            }else if (stateWithReason.isLinkLoss()) {
                                showToast("连接不见了");
                            }else if (stateWithReason.isTimeout()) {
                                showToast("连接超时");
                            }else {
                                showToast("正在检查连接...");
                            }
                        }
                        break;
                    case DISCONNECTING:
                        Log.e(TAG,"onConnection DISCONNECTING");
                        dialog.dismiss();
                        showToast("连接失败");
                        break;
                }
            });

        }

        /**
         * 测试长数据写入
         * @param data
         */
        public void sent(Data data){
            if (isReady()){
                bleManager.send(data);
            }
        }

        public void write(Data data){
            if (isReady()){
                //bleManager.writeData(data);
                //添加写入指令到队列里面
                WriteQueue.getInstance(bleManager).put(1000,data);
            }
        }

        public void read(Data data){
            if (isReady()){
                //bleManager.readData(data);
                //添加读取指令到队列里面
                WriteQueue.getInstance(bleManager).put(1000,data);
            }
        }

        /**
         * Disconnects from the sensor.
         */
        public final void disconnect() {
            WriteQueue.getInstance(bleManager).clear();
            final int state = bleManager.getConnectionState();
            if (state == BluetoothGatt.STATE_DISCONNECTED || state == BluetoothGatt.STATE_DISCONNECTING) {
                bleManager.close();
                return;
            }
            bleManager.disconnect().enqueue();

            //TODO 发送刷新触发动作
        }


        /**
         * Returns the device address
         *
         * @return device address
         */
        public String getDeviceAddress() {
            return bleManager.getBluetoothDevice().getAddress();
        }

        /**
         * Returns the device name
         *
         * @return the device name
         */
        public String getDeviceName() {
            return bleManager.getBluetoothDevice().getName();
        }

        /**
         * Returns the Bluetooth device
         *
         * @return the Bluetooth device
         */
        public BluetoothDevice getBluetoothDevice() {
            return bleManager.getBluetoothDevice();
        }

        /**
         * 如果设备连接到传感器，则返回<code>true</code>。
         *
         * @return <code>true</code>如果设备连接到传感器，<code>则为false</code>
         */
        public boolean isConnected() {
            if (bleManager==null)return false;
            return bleManager.isConnected();
        }

        public boolean isReady(){
            if (isConnected()){
                return bleManager.isReady();
            }else {
                showToast("蓝牙未连接");
                return false;
            }
        }

        @Override
        public void log(final int level, @NonNull final String message) {
            Logger.log(logSession, level, message);
        }

        @Override
        public void log(final int level, final @StringRes int messageRes, final Object... params) {
            Logger.log(logSession, level, messageRes, params);
        }
    }

    /**
     * 返回在onCreate（）中创建的处理程序。
     * 处理程序可用于推迟某些操作的执行或在UI线程中运行它们。
     */
    protected Handler getHandler() {
        return handler;
    }

    /**
     *返回绑定器实现。这必须返回实现可在activity中使用的附加管理器接口的类。
     * @return 服务绑定器
     */
    protected LocalBinder getBinder() {
        // 默认实现返回基本绑定器。您可以用自己更广泛的实现覆盖LocalBinder
        return new LocalBinder();
    }

    @Override
    public IBinder onBind(final Intent intent) {
        super.onBind(intent);
        return getBinder();
    }

    @SuppressWarnings("unchecked")
    @Override
    public void onCreate() {
        super.onCreate();
        handler = new Handler();
        // 初始化管理器
        bleManager = new BleProfileManager(this);
        dialog=new ProgressDialog(this);
        //8.0系统加强后台管理，禁止在其他应用和窗口弹提醒弹窗，如果要弹，必须使用TYPE_APPLICATION_OVERLAY，否则弹不出
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            dialog.getWindow().setType((WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY));
        }else {
            dialog.getWindow().setType((WindowManager.LayoutParams.TYPE_SYSTEM_ALERT));
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Logger.e(logSession, "Service destroyed");
        // 关闭管理器
        bleManager.close();
        bleManager = null;
        logSession = null;
        handler = null;
    }

    /**
     * 将消息显示为Toast通知。这个方法是线程安全的，你可以从任何线程调用它
     *
     * @param message 要显示的消息
     */
    protected void showToast(final String message) {
        handler.post(() -> Toast.makeText(BleProfileService.this, message, Toast.LENGTH_SHORT).show());
    }

}
